
/* = Includes =============================================================== */
#include <stdio.h>

#include <util/common_macros.h>
#include <util/mem.h>
#include "matrix.h"


// =============================================================================
ImpMatrix * imp_matrix_new_identity(int dim) {
	int i;
	ImpMatrix * mat;

	mat = imp_matrix_new(dim, dim);
	for (i = 0; i < dim; i++) {
		mat->data[i * dim + i] = 1;
	}
	return mat;
}
ImpMatrix * imp_matrix_new_ones(int rows, int columns) {
	int i;
	ImpMatrix * mat;

	mat = imp_matrix_new(rows, columns);
	for (i = 0; i < mat->size; i++) {
		mat->data[i] = 1;
	}
	return mat;
}
ImpMatrix * imp_matrix_new_rand(int rows, int columns, real min, real max) {
	int i;
	ImpMatrix * mat;
	real val;

	mat = imp_matrix_new(rows, columns);

	for (i = 0; i < mat->size; i++) {
		val = (real) (min + (rand() * (max - min)) / (real) RAND_MAX);
		mat->data[i] = val;
	}
	return mat;
}
ImpMatrix * imp_matrix_new_copy(ImpMatrix * M) {

	ImpMatrix * C;
	int i;

	C = imp_matrix_new(M->rows, M->columns);

	for (i = 0; i < M->size; i++) C->data[i] = M->data[i];

	return C;
}
void imp_matrix_clear(ImpMatrix * mat) {
	long int r;
	for (r = 0; r < mat->size; r++) {
		mat->data[r] = 0.0;
	}
}
void imp_matrix_copy(ImpMatrix * src, ImpMatrix ** dest) {

	int idx;

	_exit_if_fail(dest);
	if (*dest == NULL) *dest = imp_matrix_new(src->rows, src->columns);

	for (idx = 0; idx < src->size; idx++) {
		(*dest)->data[idx] = src->data[idx];
	}
}
void imp_matrix_print(ImpMatrix * M) {
	int c, r, _r, idx;

	if (M == NULL) {
		printf("ImpMatrix is Null\n");
		return;
	}

	for (r = 0; r < M->rows; r++) {
		_r = r * M->columns;
		for (c = 0; c < M->columns; c++) {
			idx = _r + c;
			printf("%.4f\t", M->data[idx]);
		}
		printf("\n");
	}
	printf("\n");
}
ImpMatrix * imp_matrix_cut(ImpMatrix * A, int r0, int c0, int r1, int c1) {
	ImpMatrix * cut;

	cut = imp_matrix_new(r1 - r0 + 1, c1 - c0 + 1);

	int r, c;
	for (r = 0; r < cut->rows; r++) {
		for (c = 0; c < cut->columns; c++) {
			cut->data[ r * cut->columns + c ] = A->data[ (r0 + r) * A->columns + (c0 + c) ];
		}
	}
	return cut;
}
void imp_matrix_normailze(ImpMatrix * A, real min, real max) {
	long int i;
	real MAX;
	real MIN;

	real k;

	MAX = MIN = A->data[0];

	for (i = 0; i < A->size; i++) {
		MAX = A->data[i] > MAX ? A->data[i] : MAX;
		MIN = A->data[i] < MIN ? A->data[i] : MIN;
	}

	k = (max - min) / (MAX - MIN);

	for (i = 0; i < A->size; i++) {
		A->data[i] = (A->data[i] - MIN) * k + min;
	}
}
void imp_matrix_get_normailzed(ImpMatrix * A, ImpMatrix ** B, real min, real max) {
	long int i;
	real MAX;
	real MIN;

	real k;

	_exit_if_fail(B);
	if (*B == NULL) *B = imp_matrix_new(A->rows, A->columns);

	MAX = MIN = A->data[0];

	for (i = 0; i < A->size; i++) {
		MAX = A->data[i] > MAX ? A->data[i] : MAX;
		MIN = A->data[i] < MIN ? A->data[i] : MIN;
	}

	k = (max - min) / (MAX - MIN);

	for (i = 0; i < A->size; i++) {
		(*B)->data[i] = (A->data[i] - MIN) * k + min;
	}

}

/*

void imp_matrix_sub( ImpMatrix * A, ImpMatrix * B, ImpMatrix ** Sub) {
	int i;
	
	_exit_if_fail(Sub);
	if (*Sub == NULL) *Sub = imp_matrix_new(A->rows, A->columns);

	for (i = 0; i < A->size; i++) {
		(*Sub)->data[i] = A->data[i] - B->data[i];
	}
}
*/
